package web_tools

import (
	"context"
	"log"
	"strings"
	"time"

	"github.com/chromedp/chromedp"
	"golang.org/x/net/html"
)

// Функция для извлечения всех уникальных URL на странице
func ExtractLinks(ctx context.Context, urlMain, url string, external, internal, visit *[]string) (err error) {
	log.Println(url)
	var rawHTML string
	// Получение HTML страницы
	if err = chromedp.Run(ctx,
		chromedp.Navigate(url),
		chromedp.WaitVisible("body", chromedp.ByQuery),
		chromedp.OuterHTML("html", &rawHTML),
	); err != nil {
		return
	}

	// Парсинг HTML и извлечение ссылок
	var doc *html.Node
	if doc, err = html.Parse(strings.NewReader(rawHTML)); err != nil {
		return
	}

	fCheck := func(sl []string, link string) bool {
		for _, val := range sl {
			if val == link {
				return true
			}
		}
		return false
	}

	fAppend := func(sl *[]string, link string) {
		for _, llink := range *sl {
			if llink == link {
				return
			}
		}
		*sl = append(*sl, link)
	}

	fCheckHTML := func(link string) bool {
		link = strings.Split(link, "?")[0]
		if len(link) == 0 {
			return false
		}
		if link[len(link)-1:] == "/" {
			return true
		}
		if strings.Contains(link, ".html") {
			return true
		}
		return false
	}

	fInternal := func(link string) {
		if !fCheckHTML(link) {
			log.Println("not html", link)
			return
		}
		if fCheck(*visit, link) {
			return
		}
		log.Println("internal visit", link)
		*visit = append(*visit, link)
		fAppend(internal, link)
		if err = ExtractLinks(ctx, urlMain, link, external, internal, visit); err != nil {
			return
		}
	}

	var f func(*html.Node)
	f = func(n *html.Node) {
		if n.Type == html.ElementNode && n.Data == "a" {
			for _, a := range n.Attr {
				if a.Key == "href" {
					link := a.Val
					if strings.HasPrefix(link, "/") {
						fInternal(urlMain + link)
					} else {
						if !strings.HasPrefix(link, "http") {
							continue
						}
						if strings.Contains(link, "://"+urlMain) {
							fInternal(link)
						} else {
							fAppend(external, link)
						}
					}
				}
			}
		}
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			f(c)
		}
	}
	f(doc)

	return
}

func GetLinks(url string) (external, internal []string, err error) {
	// Инициализация Chromedp
	opts := append(chromedp.DefaultExecAllocatorOptions[:],
		chromedp.Flag("headless", true), // Запустить Chrome в headless режиме
	)

	allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
	defer cancel()

	ctx, cancel := chromedp.NewContext(allocCtx)
	defer cancel()

	// Установка таймаута
	ctx, cancel = context.WithTimeout(ctx, time.Minute*10)
	defer cancel()

	external = make([]string, 0)
	internal = make([]string, 0)
	visited := make([]string, 0)

	err = ExtractLinks(ctx, url, url, &external, &internal, &visited)

	return
}
